package com.ys.util.amazon;

import com.amazon.SellingPartnerAPIAA.AWSAuthenticationCredentials;
import com.amazon.SellingPartnerAPIAA.AWSAuthenticationCredentialsProvider;
import com.amazon.SellingPartnerAPIAA.LWAAccessTokenCacheImpl;
import com.amazon.SellingPartnerAPIAA.LWAAuthorizationCredentials;
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
import com.amazonaws.services.lambda.AWSLambda;
import com.amazonaws.services.lambda.AWSLambdaClientBuilder;
import com.amazonaws.services.lambda.model.InvocationType;
import com.amazonaws.services.lambda.model.InvokeRequest;
import com.amazonaws.services.lambda.model.InvokeResult;
import com.amazonaws.services.lambda.model.ServiceException;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.ys.enume.RegionEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.naming.Context;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

public class Helper {
    static private final Logger logger = LoggerFactory.getLogger(Helper.class);

    public static void logInput(Logger logger, Object event, Context context, Gson gson) {
        logger.info("Env: " + gson.toJson(System.getenv()));
        logger.info("Ctx: " + gson.toJson(context));
        logger.info("Evt: " + gson.toJson(event));
    }

    /**
     * Support async invoke.
     *
     * @param fName
     * @param jsonInput
     */
    public static void invokeLambda(String fName, String jsonInput, Boolean async) {

        logger.info("invoking: " + fName);
        InvokeRequest invokeRequest = new InvokeRequest()
                .withFunctionName(fName)
                .withPayload(jsonInput);
        if (async) {
            invokeRequest.setInvocationType(InvocationType.Event);
        }
        InvokeResult invokeResult = null;

        try {
            AWSLambda awsLambda = AWSLambdaClientBuilder.standard()
                    .withCredentials(DefaultAWSCredentialsProviderChain.getInstance())
                    .build();

            invokeResult = awsLambda.invoke(invokeRequest);
            logger.info("invocation completed");
        } catch (ServiceException e) {
            logger.error("cannot invoke function ", e);
            throw e;
        }
    }

    private static Calendar calendar = Calendar.getInstance();

    /**
     * @param aheadSec if giving 0 then return current time string in iso format. If giving 1 then return the
     *                 time 1 second before current.
     * @return
     */
    public static String getIso8601Time(int aheadSec) {
        TimeZone tz = TimeZone.getTimeZone("UTC");
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); // Quoted "Z" to indicate UTC, no timezone offset
        df.setTimeZone(tz);
        final Date current = new Date();
        calendar.setTime(current);
        calendar.add(Calendar.SECOND, -aheadSec);

        return df.format(calendar.getTime());
    }

    public static String getIso8601Time(String dateTime) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); // Quoted "Z" to indicate UTC, no timezone offset
//		Date current = DateUtil.localToUTC(dateTime);
        TimeZone timeZone = TimeZone.getTimeZone("UTC");
        df.setTimeZone(timeZone);
        Date current = new Date(Long.parseLong(dateTime));
        return df.format(current);
    }

    private static final Gson gson = new GsonBuilder().setPrettyPrinting().create();

    // To share the cache.
    public static final LWAAccessTokenCacheImpl LWA_ACCESS_TOKEN_CACHE = new LWAAccessTokenCacheImpl();

    private static AWSAuthenticationCredentials getAwsAuthenticationCredentials(SellerSecretsVO jsonSellerSecrets) {
        return AWSAuthenticationCredentials
                .builder()
                .accessKeyId(jsonSellerSecrets.getAWSAuthenticationCredentials_AK())
                .secretKey(jsonSellerSecrets.getAWSAuthenticationCredentials_SK())
                .region(RegionEnum.from(jsonSellerSecrets.getMarketPlace()).getAwsRegion())
                .build();
    }

    private static LWAAuthorizationCredentials getLwaAuthorizationCredentials(SellerSecretsVO jsonSellerSecrets) {
        return LWAAuthorizationCredentials
                .builder()
                .clientId(jsonSellerSecrets.getlWAAuthorizationCredentials_clientid())
                .clientSecret(jsonSellerSecrets.getLWAAuthorizationCredentials_clientSecret())
                .refreshToken(jsonSellerSecrets.getLWAAuthorizationCredentials_refreshToken())
                .endpoint("https://api.amazon.com/auth/o2/token")
                .build();
    }

    public static AWSAuthenticationCredentialsProvider getAwsAuthenticationCredentialsProvider(SellerSecretsVO jsonSellerSecrets) {
        return AWSAuthenticationCredentialsProvider
                .builder()
                .roleArn(jsonSellerSecrets.getAWSAuthenticationCredentialsProvider_roleArn())
                .roleSessionName(jsonSellerSecrets.getSeller_id())
                .build();
    }

    public static <T> T buildApi(SellerSecretsVO jsonSellerSecrets,Class<T> tClass) {

         ApiClient client = new ApiClientBuilder().awsAuthenticationCredentials(getAwsAuthenticationCredentials(jsonSellerSecrets))
                .awsAuthenticationCredentialsProvider(getAwsAuthenticationCredentialsProvider(jsonSellerSecrets))
                .lwaAuthorizationCredentials(getLwaAuthorizationCredentials(jsonSellerSecrets))
                .endpoint(RegionEnum.from(jsonSellerSecrets.getMarketPlace()).getServiceUrl())
                .lwaAccessTokenCache(LWA_ACCESS_TOKEN_CACHE)
                .build();

        T t = null;
        try {
            t = tClass.newInstance();
            tClass.getMethod("setApiClient",ApiClient.class).invoke(t,client);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return t;
    }
}
